home *** CD-ROM | disk | FTP | other *** search
- /* Domain/Name server
- * Copyright 1991/2 KA9Q, PA0GRI, DK5DC and DB3FL
- *
- * ported to WNOS from a previous PA0GRI issue by DB3FL
- *
- * some code streaming and fixing done - DB3FL.91xxxx/92xxxx
- * added cache from DK5DC - DB3FL.92xxxx
- * some fixes by WZ8Y - 9206xx
- *
- */
-
- #include "global.h"
- #include "config.h"
- #include "socket.h"
- #include "domain.h"
- #include "files.h"
- #include "netuser.h"
- #include "iface.h"
-
- #define RR_QUERY 8
- #define RR_INQUERY 9
-
- static struct rr * near resolverec __ARGS((char *name,int type));
- static struct rr * near rresolve __ARGS((char *name,int type,int16 fflag));
- static int SDom = -1;
- Cache *cache;
-
- static int near
- strxlen(char *s)
- {
- int i = 0;
-
- while(*s++ != '\0')
- i++;
- return i;
- }
-
- /* Resolve an arbitrary record */
- static struct rr * near
- resolverec(name,type)
- char *name;
- int type;
- {
- struct rr *rrp;
- char *pname = NULLCHAR, *cname = NULLCHAR;
- FILE *dbase;
- struct rr_memory *memory;
-
- if(name == NULLCHAR)
- return NULLRR;
-
- if(DBloaded)
- dbase = NULLFILE;
- else
- if((dbase = fopen(Dfile,READ_TEXT)) == NULLFILE)
- return NULLRR;
-
- memory = (struct rr_memory *)mxallocw(sizeof(struct rr_memory));
- memory->Dname[0] = '\0'; /* initialize global area */
- memory->Dttl = 3600;
- memory->Dclass = 1;
-
- /* This code can handle a few weird cases. It works when there's
- * a PTR to a CNAME to the sought record, as well as when there's a
- * CNAME to a PTR to the record. But it allows only one of each kind
- * of indirection to prevent infinite loops.
- */
- while((rrp = dfind(dbase,name,type,memory)) == NULLRR){
- /* No matching record was found, let's see if it's an alias */
- if(cname == NULLCHAR
- && (rrp = dfind(dbase,name,TYPE_CNAME,memory)) != NULLRR){
- if((cname = strxdup(rrp->rdata.name)) == NULLCHAR)
- break;
- name = cname;
- rewind(dbase);
- memory->Dname[0] = '\0'; /* initialize global area */
- memory->Dttl = 3600;
- memory->Dclass = 1;
- memory->rrp = NULLRR;
- xfree(memory->dorigin);
- memory->dorigin = NULLCHAR;
- free_rr(rrp);
- continue; /* Try again */
- }
- /* Lacking that, try a pointer entry... */
- if(pname == NULLCHAR
- && (rrp = dfind(dbase,name,TYPE_PTR,memory)) != NULLRR){
- if((pname = strxdup(rrp->rdata.name)) == NULLCHAR)
- break;
- name = pname;
- rewind(dbase);
- memory->Dname[0] = '\0'; /* initialize global area */
- memory->Dttl = 3600;
- memory->Dclass = 1;
- memory->rrp = NULLRR;
- xfree(memory->dorigin);
- memory->dorigin = NULLCHAR;
- free_rr(rrp);
- continue;
- }
- /* Nope, nothing. Give up */
- break;
- }
- fclose(dbase);
- xfree(pname);
- xfree(cname);
- xfree(memory->dorigin);
- xfree((char *)memory);
- return rrp;
- }
-
- #ifdef XXX
- /* Try to figure out if we are an authority; current strategy is:
- * if a domain server is defined we do not have athority
- */
- static int near
- haveaa(name)
- char *name;
- {
- return Dhaveaa;
-
- struct rr *rrp;
- int len, cnt = 0;
- char *cp = name;
-
- /* Try to find a SOA for the whole address and by stripping off
- the first part of the address. */
- while(cnt < 4 && (rrp = resolverec(cp,TYPE_SOA)) == NULLRR){
- if((cp = strchr(cp,'.')) == NULLCHAR)
- break;
- if(*(++cp) == '\0')
- break;
- ++cnt;
- }
- if(rrp != NULLRR){
- len = strxlen(rrp->rdata.soa->mname);
- if(rrp->rdata.soa->mname[len-1] == '.')
- --len;
- if(len == strxlen(Hostname) &&
- strncmp(Hostname,rrp->rdata.soa->mname,len) == 0){
- free_rr(rrp);
- return 1;
- }
- free_rr(rrp);
- }
- return 0;
- }
- #endif
-
- /* Main entry point for domain name -> arbitrary record resolution.
- * Returns a null pointer if name is definitely not valid.
- */
- static struct rr * near
- rresolve(name,type,fflag)
- char *name;
- int type;
- int16 fflag;
- {
- char *buf;
- int i, len, recurse = 0, auth = 0, lcount = 0;
- int16 flags;
- struct rr *rrp = NULLRR, *rr, *rrtmp;
- struct dhdr *dhdr;
- struct mbuf *bp;
- struct dserver *dp = Dlist;
-
- while((rrp = resolverec(name,type)) == NULLRR){
- if(dp == NULLDOM)
- break;
-
- if(auth == 0) {
- if(Dhaveaa) {
- #ifdef XXX
- if(haveaa(name)) { /* Quit if we are an authority */
- #endif
- return NULLRR;
- } else {
- auth = -1;
- }
- }
- if(uploadstatus)
- break;
-
- /* Not in file, send query */
- flags = DOM_DORECURSE | fflag; /* Recursion desired */
- dhdr = bld_dhdr(QUERY,QUERY,flags,NO_ERROR,name,CLASS_IN,type);
- buf = mxallocw(512); /* buf is freed by sendquery */
- len = res_mkbuf(dhdr,buf,512);
- free_dhdr(dhdr); /* actualy we need to keep the question for
- later reference when an answer comes in */
- dp->queries++;
- if(sendquery(dp->address,buf,len,&bp,dp->timeout) > 0) {
- dhdr = (struct dhdr *)mxallocw(sizeof(struct dhdr));
- ntohdomain(dhdr,&bp);
- dp->responses++;
- proc_answer(dhdr,dp,NULLFILE);
- if(dhdr->rcode != NO_ERROR) {
- break;
- } else {
- for(i = 0; i < dhdr->ancount; i++){
- rrp = copy_rr(dhdr->ans[i]);
- if(strnicmp(rrp->name,name,strxlen(name)) != 0)
- continue;
- /* Got one */
- switch(rrp->type) {
- case TYPE_CNAME:
- /* Change the query name to the
- * cname and go back again
- */
- if(++recurse == MAXCNAME)
- /* too many recursions */
- break;
-
- xfree(name);
- name = strxdup(rrp->rdata.name);
- /* rescan the responces */
- i = -1;
- continue;
- }
- break;
- }
- }
- free_dhdr(dhdr);
- break;
- }
- if(errno == EABORT)
- return NULLRR;
-
- /* Timeout; back off this one and try another server */
- dp->timeout += 5000;
- dp->missers++;
- if((dp = dp->next) == NULLDOM)
- break;
- if(++lcount > Dretries)
- return NULLRR;
- }
- rr = rrp; /* Remove any NULL records */
- while(rr != NULLRR && rr->rdlength == 0){
- rrp = rr->next;
- rr->next = NULLRR;
- free_rr(rr);
- rr = rrp;
- }
- while(rr != NULLRR && rr->next != NULLRR){
- if(rr->next->rdlength == 0){
- rrtmp = rr->next->next;
- rr->next->next = NULLRR;
- free_rr(rr->next);
- rr->next = rrtmp;
- } else
- rr = rr->next;
- }
- return rrp;
- }
-
- /*----------------------------------------------------------------------*
- *retrieve the next useable entry in cache *
- *-----------------------------------------------------------------------*/
- static Cache * near
- getentry(void)
- {
- Cache *ocap, *cap = cache;
- int i;
- time_t ti;
-
- /*-------------------------------------------------------------------*
- * scan cache for an useable entry. This might be a free entry.. *
- * cap->ti == 0 or the oldest entry in Cache *
- *--------------------------------------------------------------------*/
- time(&ti);
-
- for (i = 0; i < Dcache_size; i++) {
- if (cap->ti == 0)
- return(cap);
- if (ti >= cap->ti) {
- ti = cap->ti;
- ocap = cap;
- }
- cap++;
- }
- return(ocap);
- }
-
- /*----------------------------------------------------------------------*
- * put an entry into the cache for later access *
- *-----------------------------------------------------------------------*/
- static Cache * near
- putcache(char *name,char *host,int32 addr,Rtype type,Ctype ctype)
- {
- Cache *cap = 0;
- /*-------------------------------------------------------------------*
- * Found it, put in cache *
- *--------------------------------------------------------------------*/
- cap = getentry();
- semwait(&Cwrite,1); /* -serialize Cache access */
- /*-------------------------------------------------------------------*
- * make correct entries for valid and invalid entries *
- *--------------------------------------------------------------------*/
- if (type == Address && ctype == Found) { /* via resolve_a()*/
- sprintf(cap->name,"%.39s",strtok(name,"\t "));
- } else if (ctype == Found) /* found in file */
- sprintf(cap->name,"%.39s",host);
-
- if (type == Name && ctype == Missing) {
- cap->address = 0;
- sprintf(cap->name,"%.39s",host);
- } else
- cap->address = (ctype != Found) ? 0 : addr;
-
- cap->type = ctype;
- cap->ti = time(NULL);
- semrel(&Cwrite);
- return cap;
- }
-
- /*----------------------------------------------------------------------*
- * Perform a cache search.
- *-----------------------------------------------------------------------*/
- static Cache * near
- cache_search(char *name,Rtype type)
- {
- int i;
- char *cp;
- Cache *cap = cache;
-
- for (i = 0; i < Dcache_size; i++) {
- if(i == Dcache_size)
- break;
- if(cap->ti == 0)
- continue;
- if (type == Name) {
- if(cap->name[0] != '\0') {
- if(strchr(name,'.') == NULLCHAR) {
- if((cp = strchr(cap->name,'.')) != NULLCHAR)
- *cp = '\0';
- if(stricmp(cap->name,name) == 0) {
- *cp = '.';
- return cap;
- }
- *cp = '.';
- } else if(strnicmp(cap->name,name,(strxlen(name) - 1)) == 0)
- return cap;
- }
- } else {
- if(cap->address != 0 && cap->address == aton(name)) {
- return cap;
- }
- }
- cap++;
- }
- return(0);
- }
-
- /* Main entry point for domain name -> address resolution.
- * Returns 0 if name is definitely not valid.
- */
- int32
- resolve(name)
- char *name;
- {
- char *sname;
- int state = Found;
- int32 addr = 0;
- struct rr *arrp = NULLRR;
- Cache *cap;
-
- if(*name == '[')
- return aton(name + 1);
-
- if(isaddr(name))
- return aton(name);
-
- if((cap = cache_search(name,Name)) != 0)
- return (cap->type == Found) ? cap->address : 0;
-
- sname = strxdup(name);
-
- if((arrp = rresolve(sname,TYPE_A,DOM_CANRECURSE)) != NULLRR
- && arrp->rdlength == 4) {
- addr = arrp->rdata.addr;
- xfree(sname);
- sname = strxdup(arrp->name);
- }
- if(addr == 0)
- state = Missing;
-
- if(cap == 0)
- putcache(NULLCHAR,sname,addr,Name,state);
- xfree(sname);
- free_rr(arrp);
- return addr;
- }
-
- /* entry point for address -> domain name resolution.
- * Returns NULLCHAR if address is not found.
- */
- char *
- resolve_a(ip_address,shorten)
- int32 ip_address;
- int shorten;
- {
- static char pname[130];
- Cache *cap;
-
- if(ip_address == 0L)
- return NULLCHAR;
-
- sprintf(pname,"%u.%u.%u.%u",
- hibyte(hiword(ip_address)),
- lobyte(hiword(ip_address)),
- hibyte(loword(ip_address)),
- lobyte(loword(ip_address)));
-
- if((cap = cache_search(pname,Address)) != 0 && cap->type == Found) {
- int i = strxlen(cap->name) - 1;
- if (cap->name[i] != '.') {
- if (shorten) {
- return cap->name;
- } else if (Dsuffix) {
- sprintf(pname,"%s.%s",cap->name,Dsuffix);
- pname[strxlen(pname) - 1] = '\0';
- return pname;
- }
- } else {
- strcpy(pname, cap->name);
- if (shorten) {
- if (Dsuffix) {
- char *j = strstr(pname, Dsuffix);
- if (j > pname && *(--j) == '.')
- *j = '\0';
- else
- pname[strxlen(pname)-1] = '\0';
- return pname;
- }
- } else {
- pname[i] = '\0';
- return pname;
- }
- }
- }
- return NULLCHAR;
-
- #ifdef notdef
-
- struct rr *rrp, *irrp, *prrp;
-
- sprintf( pname, "%u.%u.%u.%u%s",
- lobyte(loword(ip_address)),
- hibyte(loword(ip_address)),
- lobyte(hiword(ip_address)),
- hibyte(hiword(ip_address)),
- shorten ? "" : ".IN-ADDR.ARPA." );
-
- irrp = make_rr(RR_INQUERY,NULLCHAR,CLASS_IN,TYPE_A,0,4,&ip_address);
- prrp = make_rr(RR_QUERY,pname,CLASS_IN,TYPE_PTR,0,0,NULL);
-
- irrp->next = prrp; /* make list to speed search */
-
- for(dname = NULLCHAR; dname == NULLCHAR;){
- if((rrp=dcache_search(irrp)) == NULLRR
- && (rrp=dfile_search(irrp)) == NULLRR
- && (rrp=dns_query(prrp,1)) == NULLRR)
- break;
- if(rrp->rdlength == 0)
- break;
- switch(rrp->type){
- case TYPE_A:
- dname = strxdup(rrp->name);
- break;
- case TYPE_PTR:
- dname = strxdup(rrp->rdata.name);
- break;
- default:
- free_rr(rrp);
- }
- }
- free_rr(irrp);
- free_rr(prrp);
- free_rr(rrp);
- return dname;
- #endif
- }
-
- /* Main entry point for MX record lookup.
- * Returns NULLCHAR if name is currently unresolvable.
- */
- char *
- resolve_mailb(name)
- char *name;
- {
- struct rr *rrp, *arrp;
- char *sname, *tmp, *cp;
- int32 addr = 0;
- int16 pref = MAXINT16;
-
- if(name == NULLCHAR)
- return NULLCHAR;
-
- if(isaddr(name)) {
- if((sname = resolve_a(aton(name),FALSE)) == NULLCHAR)
- return NULLCHAR;
- } else {
- sname = mxallocw(strxlen(name) + 2);
- sprintf(sname,"%s.",name);
- }
- cp = sname;
-
- while(1){
- rrp = arrp = rresolve(sname,TYPE_MX,DOM_CANRECURSE);
- rrp = NULLRR;
- /* Search this list of rr's for an MX record */
- while(rrp != NULLRR){
- if(rrp->rdlength > 0 && rrp->rdata.mx.pref <= pref
- && (addr = resolve(rrp->rdata.mx.exch)) != 0L) {
- pref = rrp->rdata.mx.pref;
- }
- rrp = rrp->next;
- }
- free_rr(arrp);
- if(addr != 0)
- break;
- /* Compose wild card one level up */
- if((cp = strchr(cp,'.')) == NULLCHAR)
- break;
- tmp = mxallocw(strxlen(cp)+2);
- sprintf(tmp,"*%s",cp); /* wildcard expansion */
- xfree(sname);
- sname = tmp;
- cp = sname + 2;
- }
-
- if(Dsuffix != NULLCHAR && addr != 0) {
- tmp = mxallocw(strxlen(sname) + strxlen(Dsuffix) + 2);
- sprintf(tmp,"%s.%s",sname,Dsuffix);
- xfree(sname);
- return tmp;
- }
- xfree(sname);
- return NULLCHAR;
- }
-
- #ifdef XXX
- /* process outgoing zoneinit */
- static void
- proc_bootp(s,d,b)
- int s;
- void *d;
- void *b;
- {
- int i, count, len, auth, answers = 5;
- char *buf, *name;
- struct sockaddr_in server;
- struct rr *rrp;
- struct quest *qp;
- struct rr_memory *memory;
- FILE *fp;
- struct mbuf *bp;
- struct dserver *dp = (struct dserver *) d;
- struct dhdr *dhdr = (struct dhdr *) b;
-
- if(dhdr->qdcount != 1) {
- free_dhdr(dhdr);
- xfree((char *)dp);
- return;
- }
- qp = dhdr->qlist[0]; /* expecting only 1 question */
-
- if(qp->qtype == TYPE_ANY) {
- auth = DOM_AUTHORITY | DOM_CANRECURSE;
- name = strxdup(qp->qname);
- i = strxlen(name);
- if(name[--i] == '.')
- name[i] = '\0'; /* undo effect of dn_compress */
- dhdr->rcode = NO_ERROR;
- dhdr->aa = auth;
- dhdr->qr = RESPONSE;
- dhdr->opcode = QUERY; /* change opcode for answers */
- if((fp = fopen(name,READ_TEXT)) == NULLFILE) {
- xfree(name);
- free_dhdr(dhdr);
- xfree((char *)dp);
- return;
- }
- memory = (struct rr_memory *)mxallocw(sizeof(struct rr_memory));
- dhdr->ans = (struct rr **)cxallocw(answers,sizeof(struct rr *));
- server.sin_family = AF_INET;
- server.sin_port = dp->port;
- server.sin_addr.s_addr = dp->address;
- count = 0;
- buf = mxallocw(512);
- while((rrp = get_rr(fp,memory)) != NULLRR) {
- dhdr->ans[count++] = rrp;
- if(count == answers) {
- dhdr->ancount = answers;
- len = res_mkbuf(dhdr,buf,512);
- bp = qdata(buf,(int16)len);
- send_mbuf(s,bp,0,(char *)&server,sizeof(server));
- for(i = 0; i < answers; i++) {
- free_rr(dhdr->ans[i]);
- dhdr->ans[i] = NULLRR;
- }
- count = 0;
- alarm(Dtimeout * 1000);
- /* Wait for something to happen */
- pwait(&s);
- alarm(0L);
- }
- }
-
- dhdr->ancount = count;
- len = res_mkbuf(dhdr,buf,512);
- free_dhdr(dhdr);
- bp = qdata(buf,(int16)len);
- send_mbuf(s,bp,0,(char *)&server,sizeof(server));
- xfree(buf);
- xfree((char *)dp);
- xfree(name);
- fclose(fp);
- }
- }
- #endif
-
- /* process incoming queries */
- void
- proc_query(s,d,b)
- int s;
- void *d;
- void *b;
- {
- int i, len, auth;
- char *buf;
- struct sockaddr_in server;
- struct rr *rrp, *rrans, *rrns, *rradd, *rrtmp;
- struct quest *qp;
- struct mbuf *bp;
-
- struct dserver *dp = (struct dserver *) d;
- struct dhdr *dhdr = (struct dhdr *) b;
- rrans = rrns = rradd = NULLRR;
-
- for(i = 0; i < dhdr->qdcount; i++) {
- qp = dhdr->qlist[i];
- /* A server is testing here. ASSUMING INTERNET STYLE */
- auth = (Dhaveaa) ? (DOM_AUTHORITY | DOM_CANRECURSE) : DOM_CANRECURSE;
- #ifdef XXX
- auth = (haveaa(qp->qname)) ? (DOM_AUTHORITY | DOM_CANRECURSE) : DOM_CANRECURSE;
- #endif
- switch(qp->qtype) {
- case TYPE_A:
- if((rrp = rresolve(qp->qname,TYPE_A,DOM_CANRECURSE)) != NULLRR) {
- /* we found an entry, go tell him */
- dhdr->rcode = NO_ERROR;
- dhdr->aa = auth;
- dhdr->qr = RESPONSE;
- rrans = rrp;
- } else {
- /* we did not find an entry, go tell him */
- rrp = (struct rr *)mxallocw(sizeof(struct rr));
- rrp->name = strxdup(qp->qname);
- rrp->type = qp->qtype;
- rrp->class = qp->qclass;
- rrp->ttl = 500L;
- rrp->rdata.addr = 0L;
- rrp->rdlength = 4; /* size of addr data */
- dhdr->rcode = NAME_ERROR;
- dhdr->aa = auth;
- dhdr->qr = RESPONSE;
- rrans = rrp;
- }
- break;
- case TYPE_MB:
- case TYPE_MG:
- case TYPE_MR:
- case TYPE_MX:
- case TYPE_NS:
- case TYPE_SOA:
- case TYPE_PTR:
- case TYPE_TXT:
- case TYPE_CNAME:
- case TYPE_HINFO:
- case TYPE_ANY:
- if((rrp = rresolve(qp->qname,qp->qtype,DOM_CANRECURSE)) != NULLRR){
- dhdr->rcode = NO_ERROR;
- dhdr->aa = auth;
- dhdr->qr = RESPONSE;
- } else {
- dhdr->rcode = NAME_ERROR;
- dhdr->aa = auth;
- dhdr->qr = RESPONSE;
- }
- rrans = rrp;
- break;
- /* if I cannot give a reasonable answer , dont give it ... */
- case TYPE_MD: /* unsupported */
- case TYPE_MF: /* unsupported */
- case TYPE_WKS: /* unsupported */
- case TYPE_NULL: /* unsupported */
- case TYPE_MINFO: /* unsupported */
- default:
- dhdr->rcode = NOT_IMPL;
- dhdr->aa = auth;
- dhdr->qr = RESPONSE;
- }
- }
- i = 0;
- rrtmp = rrans;
- while(rrtmp != NULLRR) {
- i++;
- rrtmp = rrtmp->next;
- }
- dhdr->ancount = i;
- if(i > 0) {
- dhdr->ans = (struct rr **)cxallocw(i,sizeof(struct rr *));
- rrtmp = rrans;
- i = 0;
- while(rrtmp != NULLRR) {
- dhdr->ans[i] = rrtmp;
- i++;
- rrans = rrtmp;
- rrtmp = rrtmp->next;
- rrans->next = NULLRR; /* break link */
- }
- }
- i = 0;
- rrtmp = rrns;
- while(rrtmp != NULLRR) {
- i++;
- rrtmp = rrtmp->next;
- }
- dhdr->nscount = i;
- if(i > 0) {
- dhdr->ns = (struct rr **)cxallocw(i,sizeof(struct rr *));
- rrtmp = rrns;
- i = 0;
- while(rrtmp != NULLRR) {
- dhdr->ns[i] = rrtmp;
- i++;
- rrns = rrtmp;
- rrtmp = rrtmp->next;
- rrns->next = NULLRR; /* break link */
- }
- }
- i = 0;
- rrtmp = rradd;
- while(rrtmp != NULLRR) {
- i++;
- rrtmp = rrtmp->next;
- }
- dhdr->arcount = i;
- if(i > 0) {
- dhdr->add = (struct rr **)cxallocw(i,sizeof(struct rr *));
- rrtmp = rradd;
- i = 0;
- while(rrtmp != NULLRR) {
- dhdr->add[i] = rrtmp;
- i++;
- rradd = rrtmp;
- rrtmp = rrtmp->next;
- rradd->next = NULLRR; /* break link */
- }
- }
- buf = mxallocw(512);
- len = res_mkbuf(dhdr,buf,512);
- free_dhdr(dhdr);
- server.sin_family = AF_INET;
- server.sin_port = dp->port;
- server.sin_addr.s_addr = dp->address;
- bp = qdata(buf,(int16)len);
- send_mbuf(s,bp,0,(char *)&server,sizeof(server));
- xfree(buf);
- xfree((char *)dp);
- }
- /* ----------------------- Domain server start/stop ----------------------- */
-
- int
- dom1(int argc,char *argv[],void *p)
- {
- struct sockaddr_in lsocket,from;
- int fromlen;
- struct mbuf *bp;
- struct dhdr *dhdr;
- struct dserver *dp;
-
- if(SDom != -1)
- return 0;
- psignal(Curproc,0);
- chname(Curproc,"Domain listener");
- lsocket.sin_family = AF_INET;
- lsocket.sin_addr.s_addr = INADDR_ANY;
- lsocket.sin_port = (argc < 2) ? IPPORT_DOMAIN : atoi(argv[1]);
-
- SDom = socket(AF_INET,SOCK_DGRAM,0);
- bind(SDom,(char *)&lsocket,sizeof(lsocket));
- for(;;){
- fromlen = sizeof(from);
- if(recv_mbuf(SDom,&bp,0,(char *)&from,&fromlen) == -1)
- break;
- dhdr = (struct dhdr *)mxallocw(sizeof(struct dhdr));
- if (ntohdomain(dhdr,&bp) == -1)
- continue; /* something wrong with this packet */
- if(dhdr->qr != RESPONSE) {
- dp = (struct dserver *)mxallocw(sizeof(struct dserver));
- dp->address = from.sin_addr.s_addr;
- dp->port = from.sin_port;
- if(dhdr->opcode != ZONEINIT)
- newproc("Domain query",1024,proc_query,SDom,(void *)dp,(void *)dhdr,0);
- }
- }
- return 0;
- }
-
- int
- dom0(int argc,char *argv[],void *p)
- {
- close_s(SDom);
- SDom = -1;
- return 0;
- }
-
-
-